package com.movie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.movie.entity.*;
import com.movie.mapper.CinemaMapper;
import com.movie.service.ICinemaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.movie.vo.PageResultVO;
import com.movie.vo.Result;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xsl
 * @since 2021-04-14
 */
@Service
public class CinemaServiceImpl extends ServiceImpl<CinemaMapper, Cinema> implements ICinemaService {
    @Autowired(required = false)
    private CinemaMapper cinemaMapper;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private ICinemaService iCinemaService;

    @Value("${topic.page}")
    private String PAGETOPIC;

    @Value("${tag.page}")
    private String PAGETAG;

    @Override
    public Result findCinemaInfo() {

        List<Cinema> cinemaInfo = cinemaMapper.findCinemaInfo();
        //System.out.println(cinemaInfo);

        //同步索引库
        cinemaInfo.forEach(cinema -> {

            ESCinema esCinema = new ESCinema();
            if (cinema.getCinemaId() == null) return;
            esCinema.setCinema_id(cinema.getCinemaId());
            esCinema.setCinema_name(cinema.getCinemaName());
            esCinema.setCity_id(cinema.getCity().getCityId());
            esCinema.setCity_name(cinema.getCity().getCityName());

            Cinemabrand cinemabrand = cinema.getCinemabrand();
            if (cinemabrand == null) {
                cinemabrand = new Cinemabrand();
            }

            esCinema.setCinemabrand_id(cinemabrand.getCinemabrandId());
            esCinema.setCinemabrand_name(cinemabrand.getCinemabrandName());

            Region region = cinema.getRegion();
            if (region == null) region = new Region();
            esCinema.setRegion_id(region.getRegionId());
            esCinema.setRegion_name(region.getRegionName());

            Hall hall = cinema.getHall();
            if (hall == null) hall = new Hall();
            esCinema.setHall_id(hall.getHallId());
            esCinema.setHall_type(hall.getHallType());

            Movie movie = cinema.getMovie();
            if (movie == null) movie = new Movie();
            esCinema.setPrice(movie.getPrice());
            esCinema.setAddress(cinema.getAddress());
            elasticsearchRestTemplate.save(esCinema);
        });

        return new Result(true, "保存成功");

    }

    @Override
    public PageResultVO<ESCinema> search(Map searchMap) {
        if (searchMap == null) {
            return new PageResultVO<>(false, "参数不合法");
        }
        //构造查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(searchMap.get("cityName"))) {

            MatchQueryBuilder cityNameQueryBuilder = QueryBuilders.
                    matchQuery("city_name", searchMap.get("cityName"));
            //品牌
            MatchQueryBuilder cinemabrandNameQueryBuilder = QueryBuilders.
                    matchQuery("cinemabrand_name", searchMap.get("cinemabrandName"));
            //区
            MatchQueryBuilder regionNameQueryBuilder = QueryBuilders.
                    matchQuery("region_name", searchMap.get("regionName"));

            MatchQueryBuilder hallTypeQueryBuilder = QueryBuilders
                    .matchQuery("hall_type", searchMap.get("hallType"));


            boolQueryBuilder.should(cityNameQueryBuilder);
            boolQueryBuilder.should(cinemabrandNameQueryBuilder);
            boolQueryBuilder.should(regionNameQueryBuilder);
            boolQueryBuilder.should(hallTypeQueryBuilder);
        }


        //设置分页
        int page = 0;
        if (!StringUtils.isEmpty(searchMap.get("page"))) {
            page = (int) searchMap.get("page");
            page--;
        }
        int size = 3;
        if (!StringUtils.isEmpty(searchMap.get("size"))) {
            size = (int) searchMap.get("size");
        }
        PageRequest pageRequest = PageRequest.of(page, size);

        //聚合
        TermsAggregationBuilder cinemabrandNameAggBuilder = AggregationBuilders.terms("cinemabrandName_agg") //取别名
                .field("cinemabrand_name.keyword");
        TermsAggregationBuilder regionNameAggBuilder = AggregationBuilders.terms("regionName_agg")
                .field("region_name.keyword");
        TermsAggregationBuilder hallTypeAggBuilder = AggregationBuilders.terms("hallType_agg")
                .field("hall_type.keyword");

        //过滤[品牌，行政区，特殊厅]
        if (!StringUtils.isEmpty((String) searchMap.get("cinemabrandNameFilter"))) {
            TermQueryBuilder cinemabrandNameQueryBuilder = QueryBuilders
                    .termQuery("cinemabrand_name.keyword", searchMap.get("cinemabrandNameFilter"));
            boolQueryBuilder.filter(cinemabrandNameQueryBuilder);

        }
        if (!StringUtils.isEmpty((String) searchMap.get("regionNameFilter"))) {
            TermQueryBuilder regionNameQueryBuilder = QueryBuilders
                    .termQuery("region_name.keyword", searchMap.get("regionNameFilter"));
            boolQueryBuilder.filter(regionNameQueryBuilder);
        }
        if (!StringUtils.isEmpty((String) searchMap.get("hallTypeFilter"))) {
            TermQueryBuilder hallTypeQueryBuilder = QueryBuilders
                    .termQuery("hall_type.keyword", searchMap.get("hallTypeFilter"));
            boolQueryBuilder.filter(hallTypeQueryBuilder);
        }


        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageRequest)
                .addAggregation(cinemabrandNameAggBuilder)
                .addAggregation(regionNameAggBuilder)
                .addAggregation(hallTypeAggBuilder)
                .build();

        SearchHits<ESCinema> res = elasticsearchRestTemplate.search(build, ESCinema.class);
        System.out.println(res);
        //获取总记录数
        long totalHits = res.getTotalHits();
        List<ESCinema> esCinemas = new ArrayList<>();

        //获取当前页数据
        List<SearchHit<ESCinema>> searchHits = res.getSearchHits();
        searchHits.forEach(item -> {
            //获取文档内容
            ESCinema content = item.getContent();
            esCinemas.add(content);
        });

        //获取聚合信息
        Aggregations aggregations = res.getAggregations();
        //获取聚合结果集【品牌】
        List cinemabrandNameList = new ArrayList();
        Terms cinemabrandName_agg = aggregations.get("cinemabrandName_agg");
        List<? extends Terms.Bucket> buckets = cinemabrandName_agg.getBuckets();
        buckets.forEach(bucket -> {
            cinemabrandNameList.add(bucket.getKey());

        });
        //获取聚合结果集【区】
        List regionNameList = new ArrayList();
        Terms regionName_agg = aggregations.get("regionName_agg");
        regionName_agg.getBuckets().forEach(bucket -> {
            regionNameList.add(bucket.getKey());
        });
        //获取聚合结果集【厅】
        List hallTypeList = new ArrayList();
        Terms hallType_agg = aggregations.get("hallType_agg");
        hallType_agg.getBuckets().forEach(bucket -> {
            hallTypeList.add(bucket.getKey());
        });


        SearchPageResult pageInfo = new SearchPageResult();
        pageInfo.setTotal(totalHits);
        pageInfo.setData(esCinemas);
        pageInfo.setCinemabrandNameList(cinemabrandNameList);
        pageInfo.setRegionNameList(regionNameList);
        pageInfo.setHallTypeList(hallTypeList);

        return pageInfo;
    }

    @Override
    public Result auditCinema(Integer cinema_id) {

        //生成静态化页面

        SendResult sendResult = rocketMQTemplate.syncSend(PAGETOPIC + ":" + PAGETAG, cinema_id);
        SendStatus sendStatus = sendResult.getSendStatus();
        if (sendStatus == sendStatus.SEND_OK) {
            return new Result(true, "生成成功");
        }else{
            return new Result(false, "生成失败");
        }
    }

    @Override
    public List<Cinema> findCinemaDetail(Integer cinema_id) {
        QueryWrapper<Cinema> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("cinema_id",cinema_id);
        return iCinemaService.list(queryWrapper);
    }

    @Override
    public List<Movie> findMovie(Integer cinema_id) {
        return cinemaMapper.findMovie(cinema_id);
    }
}
